package jnpf.engine.custom.type;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import jnpf.base.UserInfo;
import jnpf.engine.custom.cmd.execution.GetRootExecutionEntityCmd;
import jnpf.engine.custom.constants.BasicActivitiConstants;
import jnpf.engine.custom.helper.UserTaskNodeHelper;
import jnpf.engine.entity.*;
import jnpf.engine.enums.*;
import jnpf.engine.model.FlowTaskDTO;
import jnpf.engine.model.FlowTaskNodeDTO;
import jnpf.engine.model.FlowTaskOperatorDTO;
import jnpf.engine.model.FlowTaskOperatorRecordDTO;
import jnpf.engine.model.flowbefore.FlowTemplateAllModel;
import jnpf.engine.model.flowengine.FlowModel;
import jnpf.engine.model.flowengine.shuntjson.childnode.*;
import jnpf.engine.model.flowengine.shuntjson.childnode.Properties;
import jnpf.engine.model.flowmessage.FlowMsgModel;
import jnpf.engine.model.flowtask.WorkTimeoutJobModel;
import jnpf.engine.service.*;
import jnpf.engine.util.*;
import jnpf.job.WorkTimeoutJobUtil;
import jnpf.model.flow.FlowFormDataModel;
import jnpf.permission.service.UserRelationService;
import jnpf.permission.service.UserService;
import jnpf.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.event.FlowableEntityEventImpl;
import org.flowable.engine.*;
import org.flowable.engine.impl.RepositoryServiceImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;

import java.util.*;

import static jnpf.engine.custom.constants.BasicActivitiConstants.AUTO_TRANSFER_ASSIGNEE;
import static jnpf.engine.custom.constants.BasicActivitiConstants.taskDescriptionSeparator;
import static jnpf.engine.custom.constants.GlobalProcessVariableConstants.*;
import static jnpf.engine.custom.constants.RootExecutionVariableConstants.MULTI_INSTANCE_FIRST_FLAG;
import static jnpf.engine.util.BpmnModelUtils.*;
import static jnpf.engine.util.EvalUtils.formData;


@Component
@Slf4j
@SuppressWarnings("all")
public class TaskCreatedInitListener implements FlowableEventListener {


    public FlowTaskOperatorEntity createOperator(FlowTaskOperatorDTO flowTaskOperatorDTO){
        FlowTaskOperatorEntity operator = new FlowTaskOperatorEntity();
        operator.setId(RandomUtil.uuId());
        operator.setHandleId(flowTaskOperatorDTO.getAssignee());
        operator.setTaskNodeId(flowTaskOperatorDTO.getTaskId());
        operator.setTaskId(flowTaskOperatorDTO.getProcessInstanceId());
        operator.setNodeCode(flowTaskOperatorDTO.getTaskDefinitionKey());
        operator.setNodeName(flowTaskOperatorDTO.getTaskName());
        operator.setDescription(flowTaskOperatorDTO.getDescription());
        operator.setCreatorTime(new Date());
        operator.setCompletion(FlowNature.ProcessCompletion);
        operator.setState(FlowNodeEnum.Process.getCode());
        operator.setDraftData(flowTaskOperatorDTO.getDraftData());
        return operator;
    }

    /**
     *
     * @param activitiEvent
     */
    @Override
    public void onEvent(FlowableEvent activitiEvent) {
        if (!(activitiEvent instanceof FlowableEntityEventImpl)) {
            return;
        }

        FlowableEntityEventImpl activitiEntityEventImpl = (FlowableEntityEventImpl) activitiEvent;
        String executionId = activitiEntityEventImpl.getExecutionId();
        Object entity = activitiEntityEventImpl.getEntity();
        //TaskEntity可以有 3个备用字段   scopeDefinition1Id  scopeId
        if (!(entity instanceof TaskEntity)) {
            return;
        }
        TaskEntity taskEntity = (TaskEntity) entity;
        UserService usersApi = SpringContextHolder.getBean(UserService.class);
        FlowTaskOperatorRecordService flowTaskOperatorRecordService = SpringContextHolder.getBean(FlowTaskOperatorRecordService.class);
        UserTaskNodeHelper userTaskNodeHelper = SpringContextHolder.getBean(UserTaskNodeHelper.class);
        ManagementService managementService = SpringContextHolder.getBean(ManagementService.class);
        FlowTaskCirculateService flowTaskCirculateService = SpringContextHolder.getBean(FlowTaskCirculateService.class);
        UserRelationService userRelationService = SpringContextHolder.getBean(UserRelationService.class);
        FlowTaskOperatorService flowTaskOperatorService = SpringContextHolder.getBean(FlowTaskOperatorService.class);
        ServiceAllUtil serviceAllUtil = SpringContextHolder.getBean(ServiceAllUtil.class);
        HistoryService historyService = SpringContextHolder.getBean(HistoryService.class);
        RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
        FlowMsgUtil flowMsgUtil = SpringContextHolder.getBean(FlowMsgUtil.class);
        TaskService taskService = SpringContextHolder.getBean(TaskService.class);
        FlowTaskUtil flowTaskUtil = SpringContextHolder.getBean(FlowTaskUtil.class);
        FlowTemplateJsonService flowTemplateJsonService = SpringContextHolder.getBean(FlowTemplateJsonService.class);
        RuntimeService runtimeService = SpringContextHolder.getBean(RuntimeService.class);


        String processDefinitionId = taskEntity.getProcessDefinitionId();
        String taskDefinitionKey = taskEntity.getTaskDefinitionKey();
        String processInstanceId = taskEntity.getProcessInstanceId();
        ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
        ExecutionEntity rootExecutionEntity = executionEntityManager.findById(processInstanceId);
        String businessKey = rootExecutionEntity.getProcessInstanceBusinessKey();
        String applyUserId = (String) rootExecutionEntity.getVariable(BasicActivitiConstants.startEventInitiator);

        List<FlowTaskCirculateEntity> circulateList = new ArrayList<>();
        //
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)
                ((RepositoryServiceImpl) getRepositoryService())
                        .getDeployedProcessDefinition(processDefinitionId);
        Map<String, Object> variables = taskEntity.getVariables();
        if(CollUtil.isEmpty(variables)){
            variables=runtimeService.getVariables(taskEntity.getProcessInstanceId());
        }
        Integer processStatus = MapUtil.getInt(variables, PROCESS_STATUS);
        String businessTitle = MapUtil.getStr(variables, BUSINESS_TITLE);
        String flowTemplateJsonId = MapUtil.getStr(variables, FLOW_TEMPLATE_JSON_ID);
        Process mainProcess = getRepositoryService().getBpmnModel(processDefinitionId).getMainProcess();
        UserTask userTask = (UserTask) mainProcess.getFlowElement(taskDefinitionKey);
        String property = getAttributeValueByTaskDefinitionKey(mainProcess, taskDefinitionKey, "userTask");


        Properties  properties = JSONObject.parseObject(property, new TypeReference<Properties>(){}) ;
        taskEntity.setCategory(processDefinitionEntity.getCategory());
        UserTask firstUserTaskNode = getFirstUserTaskNode(taskEntity.getProcessDefinitionId());
        //区分是 发起节点还是   审批节点
        Properties firstNodeProperty = getFirstNodeProperty(processDefinitionId);
//        LambdaQueryWrapper<FlowTemplateJsonEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.eq(FlowTemplateJsonEntity::getProcessDefinitionId,processDefinitionId);
//        lambdaQueryWrapper.select(FlowTemplateJsonEntity::getId);
//        FlowTemplateJsonEntity flowTemplateJsonEntity = flowTemplateJsonService.getOne(lambdaQueryWrapper);

        if(taskEntity.getTaskDefinitionKey().equals(firstUserTaskNode.getId())){
            Object tempRestart = taskEntity.getTransientVariable("tempRestart");
            Object tempFirstFlag = taskEntity.getTransientVariable("tempFirstFlag");
            if(tempRestart!=null){
                if(tempFirstFlag==null){
                    return;
                }
            }
            if(StringUtils.isBlank(taskEntity.getAssignee())){
                taskEntity.setAssignee(applyUserId);
            }
            taskEntity.setFormKey(firstNodeProperty.getFormId()+taskDescriptionSeparator+MapUtil.getStr(variables,BUSINESS_KEY));

            taskEntity.setClaimTime(new Date());
            CommandContextUtil.getHistoryManager().recordTaskInfoChange(taskEntity,taskDefinitionKey,new Date());

            //因为暂存也会启动流程实例, 所以需要判断一下
            if(!FlowTaskStatusEnum.Draft.getCode().equals(processStatus)){
                flowTaskUtil.circulateTaskList(firstNodeProperty,circulateList,null,taskEntity.getProcessInstanceId(),taskEntity);
                flowTaskCirculateService.create(circulateList);
            }


            FlowTaskOperatorDTO  flowTaskOperatorDTO = new FlowTaskOperatorDTO();
            flowTaskOperatorDTO.setTaskName(taskEntity.getName());
            flowTaskOperatorDTO.setProcessInstanceId(taskEntity.getProcessInstanceId());
            flowTaskOperatorDTO.setAssignee(taskEntity.getAssignee());
            flowTaskOperatorDTO.setTaskId(taskEntity.getId());
            flowTaskOperatorDTO.setTaskDefinitionKey(taskDefinitionKey);
            String description=taskEntity.getDescription().split(taskDescriptionSeparator)[0];
            flowTaskOperatorDTO.setDescription(description);
            FlowTaskOperatorEntity operator = createOperator(flowTaskOperatorDTO);
            flowTaskOperatorService.save(operator);

            FlowTaskOperatorRecordEntity operatorRecord = new FlowTaskOperatorRecordEntity();
            operatorRecord.setNodeCode(taskDefinitionKey);
            operatorRecord.setNodeName(taskEntity.getName());
            operatorRecord.setHandleStatus(FlowRecordEnum.submit.getCode());
            operatorRecord.setHandleId(taskEntity.getAssignee());
            operatorRecord.setReceiveTime(new Date());
            operatorRecord.setHandleTime(new Date());
            operatorRecord.setOperatorId(taskEntity.getAssignee());
            operatorRecord.setTaskOperatorId(operator.getId());
            operatorRecord.setTaskNodeId(taskEntity.getId());
            operatorRecord.setTaskId(taskEntity.getProcessInstanceId());
            operatorRecord.setId(RandomUtil.uuId());

            ActivitiNativeTaskQueryUtils activitiNativeTaskQueryUtils = SpringContextHolder.getBean(ActivitiNativeTaskQueryUtils.class);
            Long count = activitiNativeTaskQueryUtils.firstActivityFlag(taskDefinitionKey, taskEntity.getProcessInstanceId());
            if(count>=1){
                String[] split = taskEntity.getFormKey().split(taskDescriptionSeparator);
                Map<String, Object> map = flowTaskUtil.infoData(split[0], split[1]);
                MsgConfig waitMsgConfig = firstNodeProperty.getWaitMsgConfig();
                Integer on = waitMsgConfig.getOn();

                Boolean messageFlag=false;
                if(on!=0){
                    messageFlag=true;
                }
                if(messageFlag){

                    FlowTemplateAllModel templateAllModel = flowTaskUtil.templateJson(flowTemplateJsonId);
                    FlowMsgModel flowMsgModel = new FlowMsgModel();
                    if(CollUtil.isNotEmpty(circulateList)){
                        flowMsgModel.setCirculateList(circulateList);
                        flowMsgModel.setCopy(Boolean.TRUE);
                    }
                    flowMsgModel.setStartNodeProperties(firstNodeProperty);
                    flowMsgModel.setCurrentNodeProperties(properties);
//                    flowMsgModel.setNodeList(taskNodeList);
                    List<FlowTaskOperatorEntity> operatorEntityList = new ArrayList<>();
                    operatorEntityList.add(operator);
                    flowMsgModel.setOperatorList(operatorEntityList);
                    flowMsgModel.setData(map);
//                    flowMsgModel.setFlowModel(flowModel);
                    FlowTaskDTO flowTask = new FlowTaskDTO();
                    flowTask.setCreatorUserId(applyUserId);
                    flowTask.setStatus(processStatus);
                    flowTask.setFullName(businessTitle);
                    flowMsgModel.setTaskEntity(flowTask);

                    FlowTaskNodeDTO flowTaskNodeDTO = new FlowTaskNodeDTO();
                    flowTaskNodeDTO.setTaskId(processInstanceId);
                    flowTaskNodeDTO.setTaskNodeId(taskEntity.getId());
                    flowMsgModel.setTaskNodeEntity(flowTaskNodeDTO);
                    FlowModel flowModel = new FlowModel();
                    flowModel.setUserInfo(UserProvider.getUser());
                    flowMsgModel.setFlowModel(flowModel);
//                    flowMsgModel.setUserInfo(UserProvider.getUser());
                    flowMsgModel.setFlowTemplateAllModel(templateAllModel);
                    flowMsgModel.setTaskId(taskEntity.getProcessInstanceId());
                    flowMsgModel.setTaskNodeId(taskEntity.getId());
                    flowMsgUtil.message(flowMsgModel);
                }
            }
            //
            else{
                operatorRecord.setHandleStatus(FlowRecordEnum.submit.getCode());
            }
            flowTaskOperatorRecordService.save(operatorRecord);
        }
        else{
            //该任务是什么类型的????    协办任务->   普通会签任务
            //审批人 可能是哪几种???   正常->  admin  -> 自动通过的人
            String parentTaskId = taskEntity.getParentTaskId();
            if(StringUtils.isBlank(parentTaskId)){
                ExecutionEntity thirdExecutionEntity = executionEntityManager.findById(taskEntity.getExecutionId());
                String parentId = thirdExecutionEntity.getParentId();
                if(StringUtils.isBlank(properties.getFormId())){
                    taskEntity.setFormKey(firstNodeProperty.getFormId()+taskDescriptionSeparator+MapUtil.getStr(variables,BUSINESS_KEY));
                    String formKey = taskEntity.getFormKey();
                    taskEntity.setClaimTime(new Date());
                    CommandContextUtil.getHistoryManager().recordTaskInfoChange(taskEntity,taskDefinitionKey,new Date());
                }
                else{
                    Boolean taskFormEnabled = properties.getTaskFormEnabled();
                    if(taskFormEnabled!=null&& Boolean.TRUE.equals(taskFormEnabled)){
                        taskEntity.setFormKey(properties.getFormId()+taskDescriptionSeparator+taskEntity.getExecutionId());
                        Map<String, Object> data = new HashMap<>();
                        List<FlowAssignModel> assignList = properties.getAssignList();
                        String formDataId=taskEntity.getExecutionId();
                        String formId=properties.getFormId();
                        if(CollUtil.isNotEmpty(assignList)){
                            Map<String,Object> assignMap = new HashMap<>();
                            formData(assignMap, assignList,taskEntity.getProcessInstanceId());
                            data.putAll(assignMap);

                            Map<String,Map<String, Object>> dbMap = new HashMap<>();
                            dbMap.put(formDataId + "_jnpf_" +formId ,data);
                            for (String idAll : dbMap.keySet()) {
                                String[] idList = idAll.split("_jnpf_");
                                Map<String, Object> formData = dbMap.get(idAll);
                                FlowFormDataModel model = FlowFormDataModel.builder().formId(idList[1]).id(idList[0]).map(formData).formOperates(properties.getFormOperates()).build();
                                FlowContextHolder.addData(idList[0],formData);
                                serviceAllUtil.createOrUpdate(model);
                            }
                        }
                    }
                    else{
                        taskEntity.setFormKey(properties.getFormId()+taskDescriptionSeparator+parentId);
                    }
                    taskEntity.setClaimTime(new Date());
                    CommandContextUtil.getHistoryManager().recordTaskInfoChange(taskEntity,taskDefinitionKey,new Date());
                }
                ExecutionEntity executionEntity = managementService.executeCommand(new GetRootExecutionEntityCmd(taskEntity.getExecutionId(), taskDefinitionKey));
                boolean b = executionEntity.hasVariableLocal(taskDefinitionKey+MULTI_INSTANCE_FIRST_FLAG);
                if(!b){
                    executionEntity.setVariableLocal(taskDefinitionKey+MULTI_INSTANCE_FIRST_FLAG,true);
                    flowTaskUtil.circulateTaskList(properties,circulateList,null,taskEntity.getProcessInstanceId(),taskEntity);
                    flowTaskCirculateService.create(circulateList);
                }
            }


            FlowTaskOperatorDTO  flowTaskOperatorDTO = new FlowTaskOperatorDTO();
            flowTaskOperatorDTO.setTaskName(taskEntity.getName());
            flowTaskOperatorDTO.setProcessInstanceId(taskEntity.getProcessInstanceId());
            flowTaskOperatorDTO.setAssignee(taskEntity.getAssignee());
            flowTaskOperatorDTO.setTaskId(taskEntity.getId());
            flowTaskOperatorDTO.setTaskDefinitionKey(taskDefinitionKey);
            String description=taskEntity.getDescription().split(taskDescriptionSeparator)[0];
            flowTaskOperatorDTO.setDescription(description);
            FlowTaskOperatorEntity operator = createOperator(flowTaskOperatorDTO);
            FlowModel addMultiModel = FlowContextHolder.getFlowModel();
            if(addMultiModel!=null){
                operator.setParentId(addMultiModel.getParentId());
                operator.setRollbackId(addMultiModel.getRollbackId());
            }

            flowTaskOperatorService.save(operator);

            FlowTaskOperatorRecordEntity operatorRecord = new FlowTaskOperatorRecordEntity();
            operatorRecord.setNodeCode(taskDefinitionKey);
            operatorRecord.setNodeName(taskEntity.getName());
            operatorRecord.setHandleStatus(FlowRecordEnum.DOING.getCode());
            operatorRecord.setHandleId(taskEntity.getAssignee());
            operatorRecord.setReceiveTime(new Date());
            operatorRecord.setHandleTime(new Date());
            operatorRecord.setOperatorId(taskEntity.getAssignee());
            operatorRecord.setTaskOperatorId(operator.getId());
            operatorRecord.setTaskNodeId(taskEntity.getId());
            operatorRecord.setTaskId(taskEntity.getProcessInstanceId());
            operatorRecord.setId(RandomUtil.uuId());


            Map<String,Object> dataMap = new HashMap<>();

            MsgConfig waitMsgConfig = properties.getWaitMsgConfig();
            Integer on = waitMsgConfig.getOn();


            Boolean messageFlag=false;
            if(on!=0){
                messageFlag=true;
            }
            if(messageFlag){
                String formKey = taskEntity.getFormKey();
                String[] split = formKey.split(taskDescriptionSeparator);
                Map<String, Object> map = flowTaskUtil.infoData(split[0], split[1]);
                dataMap.putAll(map);
                FlowTemplateAllModel templateAllModel = flowTaskUtil.templateJson(flowTemplateJsonId);
                FlowMsgModel flowMsgModel = new FlowMsgModel();
                if(CollUtil.isNotEmpty(circulateList)){
                    flowMsgModel.setCirculateList(circulateList);
                    flowMsgModel.setCopy(Boolean.TRUE);
                }
                flowMsgModel.setStartNodeProperties(firstNodeProperty);
                flowMsgModel.setCurrentNodeProperties(properties);
//                    flowMsgModel.setNodeList(taskNodeList);
                List<FlowTaskOperatorEntity> operatorEntityList = new ArrayList<>();
                operatorEntityList.add(operator);
                flowMsgModel.setOperatorList(operatorEntityList);
                flowMsgModel.setData(map);
//                    flowMsgModel.setFlowModel(flowModel);
                FlowTaskDTO flowTask = new FlowTaskDTO();
                flowTask.setCreatorUserId(applyUserId);
                flowTask.setStatus(processStatus);
                flowTask.setFullName(businessTitle);
                flowMsgModel.setTaskEntity(flowTask);

                FlowTaskNodeDTO flowTaskNodeDTO = new FlowTaskNodeDTO();
                flowTaskNodeDTO.setTaskId(processInstanceId);
                flowTaskNodeDTO.setTaskNodeId(taskEntity.getId());
                flowMsgModel.setTaskNodeEntity(flowTaskNodeDTO);
                FlowModel flowModel = new FlowModel();
                flowModel.setUserInfo(UserProvider.getUser());
                flowMsgModel.setFlowModel(flowModel);
                flowMsgModel.setFlowTemplateAllModel(templateAllModel);
                flowMsgModel.setTaskId(taskEntity.getProcessInstanceId());
                flowMsgModel.setTaskNodeId(taskEntity.getId());
                flowMsgUtil.message(flowMsgModel);
            }


            if(StringUtils.isBlank(parentTaskId)){
                Boolean flag=false;
                String noAssignee = properties.getNoAssignee();
                if(StringUtils.isNotBlank(noAssignee)){
                    if(FlowSkipStrategyEnums.AUTO_COMPLETE.getStrategyCode().equals(noAssignee)){
                        if(AUTO_TRANSFER_ASSIGNEE.equals(taskEntity.getAssignee())){
                            operatorRecord.setHandleStatus(FlowRecordEnum.AUTO_COMPLETE.getCode());
                            operatorRecord.setHandleId(AUTO_TRANSFER_ASSIGNEE);
                            operatorRecord.setOperatorId(AUTO_TRANSFER_ASSIGNEE);
                            operatorRecord.setHandleTime(new Date());
                            operatorRecord.setHandleOpinion(FlowRecordEnum.AUTO_COMPLETE.getMessage());
                            flag=true;
                        }
                    }
                    else if(FlowSkipStrategyEnums.AUTO_REJECT.getStrategyCode().equals(noAssignee)){
                        if(AUTO_TRANSFER_ASSIGNEE.equals(taskEntity.getAssignee())){
                            runtimeService.deleteProcessInstance(taskEntity.getProcessInstanceId(),"审批人为空自动驳回");
                            operatorRecord.setHandleStatus(FlowRecordEnum.AUTO_REJECT.getCode());
                            operatorRecord.setHandleId(AUTO_TRANSFER_ASSIGNEE);
                            operatorRecord.setOperatorId(AUTO_TRANSFER_ASSIGNEE);
                            operatorRecord.setHandleTime(new Date());
                            operatorRecord.setHandleOpinion(FlowRecordEnum.AUTO_REJECT.getMessage());
                            flag=true;
                        }
                    }
                }


                Boolean hasAgreeRule = properties.getHasAgreeRule();
                if(hasAgreeRule){
                    List<Integer> agreeRules = properties.getAgreeRules();
                    if(agreeRules.contains(FlowSkipRuleEnums.ASSIGNEE_INITIATOR.getCode())){
                        if(applyUserId.equals(taskEntity.getAssignee())){
                            flag=true;
                            operatorRecord.setHandleStatus(FlowRecordEnum.ASSIGNEE_INITIATOR.getCode());
                            operatorRecord.setHandleId(taskEntity.getAssignee());
                            operatorRecord.setOperatorId(taskEntity.getAssignee());
                            operatorRecord.setHandleTime(new Date());
                            operatorRecord.setHandleOpinion(FlowRecordEnum.ASSIGNEE_INITIATOR.getMessage());
                        }
                    }
                    if(agreeRules.contains(FlowSkipRuleEnums.NO_CONDITION_COMPLETED.getCode())){
                            flag=true;
                            operatorRecord.setHandleStatus(FlowRecordEnum.audit.getCode());
                            operatorRecord.setHandleId(taskEntity.getAssignee());
                            operatorRecord.setOperatorId(taskEntity.getAssignee());
                            operatorRecord.setHandleTime(new Date());
                            operatorRecord.setHandleOpinion(FlowRecordEnum.audit.getMessage());
                    }
                    if(agreeRules.contains(FlowSkipRuleEnums.ADJACENT_NODE.getCode())){
                        //取当前节点的相邻节点
                        List<SequenceFlow> incomingFlows = userTask.getIncomingFlows();
                        //
                        List<String> list=new ArrayList();
                        getPreviousNode(list,userTask);
                        //相邻节点
                        if(CollUtil.isNotEmpty(list)){
                            List<String> adjacneUserList= new ArrayList<>();
                            List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().taskDefinitionKeys(list).processInstanceId(taskEntity.getProcessInstanceId()).list();
                            for (HistoricTaskInstance historicTaskInstance : historicTaskInstanceList) {
                                adjacneUserList.add(historicTaskInstance.getAssignee());
                            }
                            List<HistoricTaskInstanceEntity> inCache = CommandContextUtil.getEntityCache().findInCache(HistoricTaskInstanceEntity.class);
                            for (HistoricTaskInstanceEntity historicTaskInstanceEntity : inCache) {
                                if(list.contains(historicTaskInstanceEntity.getTaskDefinitionKey())){
                                    adjacneUserList.add(historicTaskInstanceEntity.getAssignee());
                                }
                            }

                            if(adjacneUserList.contains(taskEntity.getAssignee())){
                                flag=true;
                                operatorRecord.setHandleStatus(FlowRecordEnum.ADJACENT_NODE.getCode());
                                operatorRecord.setHandleId(taskEntity.getAssignee());
                                operatorRecord.setOperatorId(taskEntity.getAssignee());
                                operatorRecord.setHandleTime(new Date());
                                operatorRecord.setHandleOpinion(FlowRecordEnum.ADJACENT_NODE.getMessage());
                            }

                        }



                    }
                    if(agreeRules.contains(FlowSkipRuleEnums.ASSIGNEE_COMPLETED.getCode())){
                        List<String> completedList = taskEntity.getVariable(COMPLETED_USERS_IDS, List.class);
                        if(CollUtil.isNotEmpty(completedList) && completedList.contains(taskEntity.getAssignee())){
                            flag=true;
                            operatorRecord.setHandleStatus(FlowRecordEnum.ASSIGNEE_COMPLETED.getCode());
                            operatorRecord.setHandleId(taskEntity.getAssignee());
                            operatorRecord.setOperatorId(taskEntity.getAssignee());
                            operatorRecord.setHandleTime(new Date());
                            operatorRecord.setHandleOpinion(FlowRecordEnum.ASSIGNEE_COMPLETED.getMessage());
                        }
                    }
                }

                flowTaskOperatorRecordService.save(operatorRecord);

                if(!flag){
                    FlowModel flowModel = new FlowModel();
                    UserInfo user = UserProvider.getUser();
                    flowModel.setUserInfo(user);
                    List<FlowTaskOperatorEntity> flowTaskOperatorEntityList = new ArrayList<>();
                    flowTaskOperatorEntityList.add(operator);
                    FlowTaskEntity flowTaskEntity = new FlowTaskEntity();
                    flowTaskEntity.setId(taskEntity.getProcessInstanceId());
                    flowTaskEntity.setCreatorTime(rootExecutionEntity.getStartTime());
                    flowTaskEntity.setCreatorUserId(applyUserId);
                    flowTaskEntity.setStatus(processStatus);
                    flowTaskEntity.setFullName(businessTitle);

                    FlowTaskNodeDTO flowTaskNodeDTO = new FlowTaskNodeDTO();
                    flowTaskNodeDTO.setTaskId(processInstanceId);
                    flowTaskNodeDTO.setTaskNodeId(taskEntity.getId());

                    FlowTemplateAllModel templateAllModel = flowTaskUtil.templateJson(flowTemplateJsonId);
                    flowModel.setTaskId(taskEntity.getProcessInstanceId());
                    flowModel.setTaskNodeId(taskEntity.getId());
                    if(dataMap.size()>0){
                        insTimeOutRedis(flowModel, flowTaskOperatorEntityList, user, taskEntity.getProcessInstanceId(), properties,firstNodeProperty,flowTaskEntity,dataMap,
                                templateAllModel,flowTaskNodeDTO);
                    }
                    else{
                        String formKey = taskEntity.getFormKey();
                        String[] split = formKey.split(taskDescriptionSeparator);
                        Map<String, Object> map = flowTaskUtil.infoData(split[0], split[1]);
                        insTimeOutRedis(flowModel, flowTaskOperatorEntityList, user, taskEntity.getProcessInstanceId(), properties,firstNodeProperty,flowTaskEntity,dataMap,
                                templateAllModel,flowTaskNodeDTO);
                    }

                }
                else{
                    taskService.complete(taskEntity.getId());
                }
            }
            else{
                flowTaskOperatorRecordService.save(operatorRecord);
            }

        }
    }

    private void getPreviousNode(List list, FlowNode flowNode) {
        List<SequenceFlow> incomingFlows = flowNode.getIncomingFlows();
        for (SequenceFlow incomingFlow : incomingFlows) {
            FlowElement sourceFlowElement = incomingFlow.getSourceFlowElement();
            if(sourceFlowElement instanceof UserTask){
                list.add(sourceFlowElement.getId());
            }
            else if(sourceFlowElement instanceof  ExclusiveGateway){
                List<SequenceFlow> sequenceFlows = ((ExclusiveGateway) sourceFlowElement).getIncomingFlows();
                for (SequenceFlow sequenceFlow : sequenceFlows) {
                    getPreviousNode(list, (FlowNode) sequenceFlow.getSourceFlowElement());
                }
            }
            else if(sourceFlowElement instanceof ParallelGateway){
                List<SequenceFlow> sequenceFlows = ((ParallelGateway) sourceFlowElement).getIncomingFlows();
                for (SequenceFlow sequenceFlow : sequenceFlows) {
                    getPreviousNode(list, (FlowNode) sequenceFlow.getSourceFlowElement());
                }
            }
        }
    }

    @Override
    public boolean isFailOnException() {
        return true;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }

    private RepositoryService getRepositoryService() {
        return SpringContextHolder.getBean(RepositoryService.class);
    }


    public FlowTaskOperatorRecordEntity createOperatorRecord(FlowTaskOperatorRecordDTO flowTaskOperatorRecordDTO){
        FlowTaskOperatorRecordEntity flowTaskOperatorRecordEntity = new FlowTaskOperatorRecordEntity();
        flowTaskOperatorRecordEntity.setNodeCode(flowTaskOperatorRecordDTO.getTaskDefinitionKey());
        flowTaskOperatorRecordEntity.setNodeName(flowTaskOperatorRecordDTO.getTaskName());
        flowTaskOperatorRecordEntity.setHandleStatus(flowTaskOperatorRecordDTO.getHandleStatus());
        flowTaskOperatorRecordEntity.setHandleId(flowTaskOperatorRecordDTO.getAssignee());
        flowTaskOperatorRecordEntity.setHandleTime(new Date());
        flowTaskOperatorRecordEntity.setHandleOpinion(flowTaskOperatorRecordDTO.getHandleOpinion());
        flowTaskOperatorRecordEntity.setOperatorId(flowTaskOperatorRecordDTO.getAssignee());
//        flowTaskOperatorRecordEntity.setTaskOperatorId();
        flowTaskOperatorRecordEntity.setTaskNodeId(flowTaskOperatorRecordDTO.getTaskId());
        flowTaskOperatorRecordEntity.setTaskId(flowTaskOperatorRecordDTO.getProcessInstanceId());
        flowTaskOperatorRecordEntity.setSignImg(flowTaskOperatorRecordDTO.getSignImg());
        flowTaskOperatorRecordEntity.setStatus(flowTaskOperatorRecordDTO.getStatus());
        flowTaskOperatorRecordEntity.setFileList(flowTaskOperatorRecordDTO.getFileList());
//        flowTaskOperatorRecordEntity.setDraftData();
//        flowTaskOperatorRecordEntity.setApproverType();
//        flowTaskOperatorRecordEntity.setTenantId();
        flowTaskOperatorRecordEntity.setId(RandomUtil.uuId());
        return flowTaskOperatorRecordEntity;
    }


    private void insTimeOutRedis(FlowModel flowModel, Collection<FlowTaskOperatorEntity> operatorList, UserInfo userInfo,
                                 String processInstanceId,Properties currentProperties,Properties firstNodeProperties,
                                 FlowTaskEntity flowTaskEntity,Map<String,Object> data,FlowTemplateAllModel templateAllModel,
                                 FlowTaskNodeDTO flowTaskNodeDTO) {
        WorkTimeoutJobUtil workTimeoutJobUtil = SpringContextHolder.getBean(WorkTimeoutJobUtil.class);
        RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
        for (FlowTaskOperatorEntity operatorOne : operatorList) {
            boolean flag = ifInsRedis(currentProperties,firstNodeProperties);
            if (flag) {
                WorkTimeoutJobModel workTimeoutJobModel = WorkTimeoutJobModel.builder()
                        .flowModel(flowModel)
                        .taskId(processInstanceId).taskNodeId(operatorOne.getTaskNodeId()).
                        taskNodeOperatorId(operatorOne.getId()).operatorEntity(operatorOne)
                        .tenantId(userInfo.getTenantId())
//                        .tenantDbConnectionString(userInfo.getTenantDbConnectionString())
//                        .isAssignDataSource(userInfo.isAssignDataSource())
                        .currentProperties(currentProperties)
                        .firstNodeProperties(firstNodeProperties)
                        .flowTaskEntity(flowTaskEntity)
                        .templateAllModel(templateAllModel)
                        .data(data)
                        .flowTaskNodeDTO(flowTaskNodeDTO)
                        .taskId(processInstanceId)
                        .taskNodeId(flowModel.getTaskNodeId())
                        .build();
                workTimeoutJobUtil.insertRedis(workTimeoutJobModel, redisUtil);
            }
        }
    }
    public boolean ifInsRedis(Properties currentProperties,Properties firstNodeProperties) {
        LimitModel timeLimitConfig = currentProperties.getTimeLimitConfig();
        if (timeLimitConfig.getOn() == 0) {
            return false;
        } else if (timeLimitConfig.getOn() == 2) {
            if (firstNodeProperties.getTimeLimitConfig().getOn() == 0) {
                return false;
            }
        }
        return true;
    }
}
